using SG3L_RAG.Application.DTOs;
using SG3L_RAG.Application.Interfaces;
using SG3L_RAG.Domain.Entities;
using SG3L_RAG.Domain.Repositories;

namespace SG3L_RAG.Application.Services
{
    public class ChatService : IChatService
    {
        private readonly IRepository<Conversation> _conversationRepository;
        private readonly IRepository<Message> _messageRepository;
        private readonly IRepository<Document> _documentRepository;
        private readonly IVectorSearchService _vectorSearchService;
        private readonly IAIService _aiService;

        public ChatService(
            IRepository<Conversation> conversationRepository,
            IRepository<Message> messageRepository,
            IRepository<Document> documentRepository,
            IVectorSearchService vectorSearchService,
            IAIService aiService)
        {
            _conversationRepository = conversationRepository;
            _messageRepository = messageRepository;
            _documentRepository = documentRepository;
            _vectorSearchService = vectorSearchService;
            _aiService = aiService;
        }

        public async Task<ChatResponseDto> AskQuestionAsync(ChatRequestDto request)
        {
            try
            {
                var response = new ChatResponseDto
                {
                    IsSuccessful = false,
                    Timestamp = DateTime.UtcNow
                };

                // 1. 获取或创建对话
                var conversation = await GetOrCreateConversationAsync(request.ConversationId, request.UserId);
                response.ConversationId = conversation.Id;

                if (!request.UseRAG)
                {
                    // 如果不使用RAG，直接生成简单回答
                    var simpleAnswer = await GenerateSimpleAnswerAsync(request.Question);
                    var simpleMessage = await SaveMessageAsync(conversation.Id, request.Question, simpleAnswer, new List<DocumentSourceDto>());
                    
                    response.Answer = simpleAnswer;
                    response.MessageId = simpleMessage.Id;
                    response.IsSuccessful = true;
                    response.ConfidenceScore = 0.5f;
                    return response;
                }

                // 2. 使用RAG进行检索和生成
                var ragResult = await ProcessRAGQueryAsync(request);
                
                // 3. 保存消息
                var message = await SaveMessageAsync(conversation.Id, request.Question, ragResult.Answer, ragResult.Sources);
                
                // 4. 构建响应
                response.Answer = ragResult.Answer;
                response.MessageId = message.Id;
                response.Sources = ragResult.Sources;
                response.ConfidenceScore = ragResult.ConfidenceScore;
                response.IsSuccessful = true;

                return response;
            }
            catch (HttpRequestException httpEx)
            {
                return new ChatResponseDto
                {
                    IsSuccessful = false,
                    ErrorMessage = $"AI服务调用失败: {httpEx.Message}",
                    Timestamp = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                return new ChatResponseDto
                {
                    IsSuccessful = false,
                    ErrorMessage = $"处理失败: {ex.Message}",
                    Timestamp = DateTime.UtcNow
                };
            }
        }

        public async Task<ChatHistoryDto> GetChatHistoryAsync(Guid userId, int page = 1, int pageSize = 20)
        {
            try
            {
                var conversations = await _conversationRepository.GetAllAsync();
                var userConversations = conversations.Where(c => c.UserId == userId).ToList();

                var allMessages = await _messageRepository.GetAllAsync();
                var userMessages = allMessages
                    .Where(m => userConversations.Any(c => c.Id == m.ConversationId))
                    .OrderByDescending(m => m.CreatedAt)
                    .ToList();

                var totalCount = userMessages.Count;
                var skip = (page - 1) * pageSize;
                var pagedMessages = userMessages.Skip(skip).Take(pageSize).ToList();

                var documents = await _documentRepository.GetAllAsync();
                var documentDict = documents.ToDictionary(d => d.Id);

                var messageDtos = pagedMessages.Select(m => new ChatMessageDto
                {
                    Id = m.Id,
                    Sender = m.Sender,
                    Content = m.Content,
                    Reply = m.Reply,
                    CreatedAt = m.CreatedAt,
                    ConfidenceScore = m.ConfidenceScore,
                    Sources = m.ReferencedDocId.HasValue && documentDict.ContainsKey(m.ReferencedDocId.Value)
                        ? new List<DocumentSourceDto>
                        {
                            new DocumentSourceDto
                            {
                                DocumentId = m.ReferencedDocId.Value,
                                Title = documentDict[m.ReferencedDocId.Value].Name
                            }
                        }
                        : new List<DocumentSourceDto>()
                }).ToList();

                return new ChatHistoryDto
                {
                    Messages = messageDtos,
                    TotalCount = totalCount,
                    Page = page,
                    PageSize = pageSize,
                    HasNextPage = totalCount > skip + pageSize
                };
            }
            catch (Exception)
            {
                return new ChatHistoryDto();
            }
        }

        public async Task ClearChatHistoryAsync(Guid userId)
        {
            try
            {
                var conversations = await _conversationRepository.GetAllAsync();
                var userConversations = conversations.Where(c => c.UserId == userId).ToList();
                var conversationIds = userConversations.Select(c => c.Id).ToList();

                if (conversationIds.Any())
                {
                    // 删除消息
                    var allMessages = await _messageRepository.GetAllAsync();
                    var userMessages = allMessages.Where(m => conversationIds.Contains(m.ConversationId));
                    var messageIds = userMessages.Select(m => m.Id);
                    await _messageRepository.DeleteRangeAsync(messageIds);

                    // 删除对话
                    await _conversationRepository.DeleteRangeAsync(conversationIds);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<bool> SaveChatAsync(Guid userId, string question, string answer, List<DocumentSourceDto> sources)
        {
            try
            {
                var conversation = await GetOrCreateConversationAsync(null, userId);
                await SaveMessageAsync(conversation.Id, question, answer, sources);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private async Task<Conversation> GetOrCreateConversationAsync(Guid? conversationId, Guid userId)
        {
            if (conversationId.HasValue)
            {
                var existingConversation = await _conversationRepository.GetByIdAsync(conversationId.Value);
                if (existingConversation != null && existingConversation.UserId == userId)
                {
                    return existingConversation;
                }
            }

            // 创建新对话
            var newConversation = Conversation.Create(userId);
            await _conversationRepository.AddAsync(newConversation);
            return newConversation;
        }

        private async Task<Message> SaveMessageAsync(Guid conversationId, string question, string answer, List<DocumentSourceDto> sources)
        {
            var referencedDocId = sources.FirstOrDefault()?.DocumentId;
            var message = Message.Create(conversationId, "user", question, answer, referencedDocId);
            
            // 计算置信度分数
            var confidenceScore = CalculateConfidenceScore(answer, sources);
            message.SetConfidenceScore(confidenceScore);
            
            await _messageRepository.AddAsync(message);
            return message;
        }

        private async Task<(string Answer, List<DocumentSourceDto> Sources, float ConfidenceScore)> ProcessRAGQueryAsync(ChatRequestDto request)
        {
            // 1. 搜索相关文档
            var searchResults = await _vectorSearchService.SearchSimilarChunksAsync(
                request.Question, 
                request.MaxResults, 
                request.SimilarityThreshold);

            if (!searchResults.Any())
            {
                var noResultAnswer = await GenerateSimpleAnswerAsync(request.Question);
                return (noResultAnswer, new List<DocumentSourceDto>(), 0.3f);
            }

            // 2. 准备上下文
            var contexts = searchResults.Select(r => r.Content).ToList();
            var documents = await _documentRepository.GetAllAsync();
            var documentDict = documents.ToDictionary(d => d.Id);

            // 3. 生成答案
            var answer = await _aiService.GenerateAnswerAsync(request.Question, contexts);

            // 4. 构建文档源
            var sources = searchResults
                .GroupBy(r => r.DocumentId)
                .Select(g =>
                {
                    var firstChunk = g.First();
                    var doc = documentDict.ContainsKey(firstChunk.DocumentId) 
                        ? documentDict[firstChunk.DocumentId] 
                        : null;
                    
                    return new DocumentSourceDto
                    {
                        DocumentId = firstChunk.DocumentId,
                        Title = doc?.Name ?? "未知文档",
                        Excerpt = TruncateText(firstChunk.Content, 200),
                        RelevanceScore = g.Max(x => x.Score),
                        ChunkIndex = firstChunk.ChunkIndex,
                        HighlightedText = firstChunk.HighlightedContent
                    };
                })
                .OrderByDescending(s => s.RelevanceScore)
                .ToList();

            // 5. 计算置信度
            var confidenceScore = CalculateConfidenceScore(answer, sources);

            return (answer, sources, confidenceScore);
        }

        private async Task<string> GenerateSimpleAnswerAsync(string question)
        {
            return await _aiService.GenerateAnswerAsync(question, new List<string>());
        }

        private float CalculateConfidenceScore(string answer, List<DocumentSourceDto> sources)
        {
            if (!sources.Any()) return 0.3f;

            var avgRelevanceScore = sources.Average(s => s.RelevanceScore);
            var sourceCount = Math.Min(sources.Count, 5);
            var lengthFactor = Math.Min(answer.Length / 100.0f, 1.0f);

            var confidenceScore = (avgRelevanceScore * 0.6f) + (sourceCount / 5.0f * 0.3f) + (lengthFactor * 0.1f);
            return Math.Max(0.1f, Math.Min(1.0f, confidenceScore));
        }

        private string TruncateText(string text, int maxLength)
        {
            if (string.IsNullOrEmpty(text) || text.Length <= maxLength)
                return text ?? string.Empty;

            var truncated = text.Substring(0, maxLength);
            var lastSpace = truncated.LastIndexOf(' ');
            return (lastSpace > 0 ? truncated.Substring(0, lastSpace) : truncated) + "...";
        }
    }
}
